package com.zmn.oms.services.impl.work;

import com.zmn.base.common.data.common.dro.company.CompanyDRO;
import com.zmn.base.common.data.dubbo.interfaces.company.CompanyListRemoteService;
import com.zmn.base.engineer.common.constants.DubboConsts;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.common.dto.OmsBaseOperator;
import com.zmn.oms.common.exception.OmsBusinessException;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.work.OrderWorkCasOperateService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.StringJoiner;

/**
 * 类描述：工单
 *
 * @author liuying
 * @date 2018/11/08 15:41
 */
@Slf4j
@Service
public class OrderWorkCasOperateServiceImpl implements OrderWorkCasOperateService {

    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    CompanyListRemoteService companyListRemoteService;
    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    EngineerListRemoteService engineerListRemoteService;
    @Resource
    private OrderWorkService orderWorkService;

    @Override
    public String getOrderCasSign(OrderWork orderWork, int opType) {
        StringJoiner param = new StringJoiner("-");

        switch (opType) {
            case OrderConsts.ORDER_OP_TYPE_ASSIGN:
                // 分单：需校验的前后数据一致的有：服务平台、城市、工单状态、工单结果，即：分单操作前后，服务平台和城市必须相同
                param.add(String.valueOf(orderWork.getPlatWork()));
                param.add(String.valueOf(orderWork.getCityId()));
                param.add(String.valueOf(orderWork.getStatus()));
                param.add(String.valueOf(orderWork.getResultStatus()));
                break;
            case OrderConsts.ORDER_OP_TYPE_ASSIGN_BACK:
                // 分单撤回：需校验的前后数据一致的有：服务平台、工单状态、工单结果
                param.add(String.valueOf(orderWork.getPlatWork()));
                param.add(String.valueOf(orderWork.getStatus()));
                param.add(String.valueOf(orderWork.getResultStatus()));
                break;
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE:
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE_BACK:
                // 操作：派单&派单撤回
                // 需校验的前后数据一致的有：服务平台、子公司、服务商、渠道、城市、工单状态、工单结果
                // 在数据前后一致性校验通过后，还需校验数据的准确性，数据维度是：服务平台、子公司、服务商（即：服务商归属的子公司、服务平台正确）
                param.add(String.valueOf(orderWork.getPlatWork()));
                param.add(String.valueOf(orderWork.getCompanyId()));
                param.add(String.valueOf(orderWork.getManageCompanyId()));
                param.add(String.valueOf(orderWork.getChannelId()));
                param.add(String.valueOf(orderWork.getCityId()));
                param.add(String.valueOf(orderWork.getStatus()));
                param.add(String.valueOf(orderWork.getResultStatus()));
                break;
            case OrderConsts.ORDER_OP_TYPE_COMPLETE:
            case OrderConsts.ORDER_OP_TYPE_CANCEL:
            case OrderConsts.ORDER_OP_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT:
            case OrderConsts.ORDER_OP_TYPE_SERVICE_ITEM:
            case OrderConsts.ORDER_OP_TYPE_ORDER_PHOTO:
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_LEVEL_ONE:
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_FREE:
            case OrderConsts.ORDER_OP_TYPE_MULTI_MASTER:
                // 操作：完成&取消&改预付款&改价格&工单照片&人工优惠&特殊优惠&多工程师
                // 需校验的前后数据一致的有：服务平台、子公司、服务商、渠道、城市、工程师、工单状态、工单结果
                // 在数据前后一致性校验通过后，还需校验数据的准确性，数据维度是：服务平台、子公司、服务商、工程师（即：服务商归属的子公司、服务平台正确）
                param.add(String.valueOf(orderWork.getPlatWork()));
                param.add(String.valueOf(orderWork.getCompanyId()));
                param.add(String.valueOf(orderWork.getManageCompanyId()));
                param.add(String.valueOf(orderWork.getChannelId()));
                param.add(String.valueOf(orderWork.getCityId()));
                // 2021-07-22 19:43:12 新需求，为了师傅调岗，不验证师傅
                // param.add(String.valueOf(orderWork.getMasterId()));
                param.add(String.valueOf(orderWork.getStatus()));
                param.add(String.valueOf(orderWork.getResultStatus()));
                break;
            default:
                return "";
        }

        log.debug("订单：{}, casSign源文：{}", orderWork, param.toString());
        return DigestUtils.md5Hex(param.toString());
    }

    @Override
    public String getOrderCasSign(Long orderId, Long workId, int opType) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, workId);
        return this.getOrderCasSign(orderWork, opType);
    }

    @Override
    public void validate(@NonNull OmsBaseOperator omsBaseOperator, int opType) throws OmsBusinessException {
        Long orderId = omsBaseOperator.getOrderId();
        Long workId = omsBaseOperator.getWorkId();

        Objects.requireNonNull(orderId);
        Objects.requireNonNull(workId);

        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, workId);
        this.casValidate(orderWork, omsBaseOperator.getCasSign(), opType);
        this.dataValidate(orderWork, opType);
    }

    private void casValidate(OrderWork orderWork, String casSign, int opType) throws OmsBusinessException {

        String orderCasSign = this.getOrderCasSign(orderWork, opType);
        log.debug("workId：{}，orderCasSign：{}，casSign：{}，opType：{}", orderWork.getOrderId(), orderCasSign, casSign, opType);

        // 签名一致 并且 数据校验通过，验证通过
        if (StringUtils.isBlank(orderCasSign) || Objects.equals(casSign, orderCasSign)) {
            return;
        }

        switch (opType) {
            case OrderConsts.ORDER_OP_TYPE_ASSIGN:
                // 分单：需校验的前后数据一致的有：服务平台、城市、工单状态、工单结果，即：分单操作前后，服务平台和城市必须相同
                throw new OmsBusinessException("工单服务平台/城市/状态/工单状态/工单结果，发生变化，请重新操作");
            case OrderConsts.ORDER_OP_TYPE_ASSIGN_BACK:
                // 分单撤回：需校验的前后数据一致的有：服务平台、工单状态、工单结果
                throw new OmsBusinessException("工单服务平台/工单状态/工单结果，发生变化，请重新操作");
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE:
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE_BACK:
                // 派单&派单撤回：需校验的前后数据一致的有：服务平台、子公司、服务商、渠道、城市、工单状态、工单结果
                // 在数据前后一致性校验通过后，还需校验数据的准确性，数据维度是：服务平台、子公司、服务商（即：服务商归属的子公司、服务平台正确）
                throw new OmsBusinessException("工单服务平台/子公司/服务商/渠道/城市/工单状态/工单结果，发生变化，请重新操作");
            case OrderConsts.ORDER_OP_TYPE_COMPLETE:
            case OrderConsts.ORDER_OP_TYPE_CANCEL:
            case OrderConsts.ORDER_OP_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT:
            case OrderConsts.ORDER_OP_TYPE_SERVICE_ITEM:
            case OrderConsts.ORDER_OP_TYPE_ORDER_PHOTO:
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_LEVEL_ONE:
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_FREE:
            case OrderConsts.ORDER_OP_TYPE_MULTI_MASTER:
                // 操作：完成&取消&改预付款&改价格&工单照片&人工优惠&特殊优惠&多工程师
                // 需校验的前后数据一致的有：服务平台、子公司、服务商、渠道、城市、工程师、工单状态、工单结果
                // 在数据前后一致性校验通过后，还需校验数据的准确性，数据维度是：服务平台、子公司、服务商、工程师（即：服务商归属的子公司、服务平台正确）
                throw new OmsBusinessException("工单服务平台/子公司/服务商/渠道/城市/工程师/工单状态/工单结果，发生变化，请重新操作");
        }

    }

    /**
     * 订单数据校验
     *
     * @param orderWork
     * @param opType
     * @return
     */
    private void dataValidate(OrderWork orderWork, int opType) throws OmsBusinessException {
        Integer manageCompanyId = orderWork.getManageCompanyId();
        if (NumberUtil.isNullOrZero(manageCompanyId)) {
            return;
        }

        switch (opType) {
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE:
            case OrderConsts.ORDER_OP_TYPE_DISTRIBUTE_BACK:
            case OrderConsts.ORDER_OP_TYPE_COMPLETE:
            case OrderConsts.ORDER_OP_TYPE_CANCEL:
            case OrderConsts.ORDER_OP_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT:
            case OrderConsts.ORDER_OP_TYPE_SERVICE_ITEM:
            case OrderConsts.ORDER_OP_TYPE_ORDER_PHOTO:
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_LEVEL_ONE:
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_FREE:
            case OrderConsts.ORDER_OP_TYPE_MULTI_MASTER:
                // 在数据前后一致性校验通过后，还需校验数据的准确性，数据维度是：服务平台、子公司、服务商、工程师（即：服务商归属的子公司、服务平台正确）
                log.debug("CAS#dataValidate#订单数据校验获取公司信息入参[{}]", manageCompanyId);
                ResponseDTO<CompanyDRO> companyByCompanyResponse = companyListRemoteService.getCompanyDROById(manageCompanyId);
                log.debug("CAS#dataValidate#订单数据校验获取公司信息出参[{}]", companyByCompanyResponse);
                CompanyDRO companyDRO = companyByCompanyResponse.getData();
                if (Objects.isNull(companyDRO) || !Objects.equals(companyDRO.getPlat(), orderWork.getPlatWork())
                        || !Objects.equals(companyDRO.getSubCompanyId(), orderWork.getCompanyId())) {
                    log.debug("CAS#dataValidate#公司信息[{}], 订单[{}]", companyByCompanyResponse, orderWork);
                    throw new OmsBusinessException("服务平台、子公司、服务商不匹配，请找运维工程师反馈问题");
                }
        }

        // 2021-07-22 19:43:12 新需求，为了师傅调岗，不验证师傅
        /*
        // 验证工程师数据
        Integer masterId = orderWork.getMasterId();
        if (NumberUtil.isNullOrZero(masterId)) {
            return;
        }

        switch (opType) {
            case OrderConsts.ORDER_OP_TYPE_COMPLETE:
            case OrderConsts.ORDER_OP_TYPE_CANCEL:
            case OrderConsts.ORDER_OP_TYPE_UPDATE_CHANNEL_PREPAY_AMOUNT:
            case OrderConsts.ORDER_OP_TYPE_SERVICE_ITEM:
            case OrderConsts.ORDER_OP_TYPE_ORDER_PHOTO:
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_LEVEL_ONE:
            case OrderConsts.ORDER_OP_TYPE_DISCOUNT_FREE:
            case OrderConsts.ORDER_OP_TYPE_MULTI_MASTER:
                // 验证工程师数据
                ResponseDTO<EngineerCompanyDRO> engineerCompanyDROResponseDTO = engineerListRemoteService.getEngineerCompanyByEngineerId(masterId);
                EngineerCompanyDRO engineerCompanyDRO = engineerCompanyDROResponseDTO.getData();
                if (Objects.isNull(engineerCompanyDRO)) {
                    return;
                }
                if (Objects.equals(engineerCompanyDRO.getManageCompanyId(), orderWork.getManageCompanyId())) {
                    return;
                }
                throw new OmsBusinessException("服务平台、子公司、服务商、工程师数据不匹配，请找运维工程师反馈问题");
        }*/
    }

}